package main

import (
	"dempsey/fileUpload/utils/fileUtils"
	"dempsey/fileUpload/utils/hash"
	"dempsey/fileUpload/utils/proto"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net"
	"net/http"
	"net/url"
	"os"
	"strconv"
)

// 小文件大小，单位为 B，这边要调的，目前大小 4MB
const chunkSize int64 = 2 << 22

// 上传文件地址
const uploadUrl = "http://localhost:8000/uploadFile"

var (
	filePath = "./data/timebook/"
	fileName = "./data/timebook/timebook.tgz"
)

func main() {
	conn, err := net.Dial("tcp", "localhost:30000")
	if err != nil {
		fmt.Println("dial failed, err", err)
		return
	}
	defer conn.Close()

	uploadFile(conn)
}

func uploadFile(conn net.Conn) {
	// 获取文件绝对地址，避免误操作
	fileName = fileUtils.GetAbsoluteFilePath(fileName)

	// 获取文件参数，校验文件存在性
	fileInfo, err := os.Stat(fileName)
	if err != nil {
		log.Printf("文件不存在，err：%v", err)
	}
	// 文件大小
	fileSize := float64(fileInfo.Size())
	// 文件 hash 值
	bigFileHash := hash.GetMd5OfFile(fileName)
	// 拆分为的小文件数量
	num := int(math.Ceil(fileSize / float64(chunkSize)))

	// 输出大文件参数
	fmt.Printf("Send: fileName:%v, fileSize:%.2fMB, bigHash:%x, num:%v\n", fileName, fileSize/float64(chunkSize), bigFileHash, num)

	// 开始传输
	data := url.Values{"fileName": {fileName}, "fileHash": {bigFileHash}, "fileNum": {strconv.Itoa(num)}}
	resp, err := http.PostForm(uploadUrl, data)
	if err != nil {
		log.Println("访问失败 1")
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("读取 body 失败 1")
	}
	fmt.Println("body1:", body)

	// 打开大文件
	fi, err := os.OpenFile(fileName, os.O_RDONLY, os.ModePerm)
	if err != nil {
		log.Println(err)
		return
	}
	// 拆分小文件
	b := make([]byte, chunkSize)
	for i := int64(1); i <= int64(num); i++ {
		fi.Seek((i-1)*(chunkSize), 0)
		// 若小文件定义大小比剩余文件大，则最后一个小文件取剩余文件大小
		if len(b) > int(fileInfo.Size()-(i-1)*chunkSize) {
			b = make([]byte, fileInfo.Size()-(i-1)*chunkSize)
		}
		fi.Read(b)
		// 改为实现发送
		smallFileName := fileName + strconv.FormatInt(i, 10)
		smallFileHash := hash.GetMd5(b)
		pkg, err := proto.Encode([]byte(smallFileName), smallFileHash, b)
		if err != nil {
			log.Println(err)
		}
		conn.Write(pkg)
	}
	fi.Close()

	// 下面是写文件，应该在 receive 那边
	//fii, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
	//if err != nil {
	//	fmt.Println(err)
	//	return
	//}
	//for i := 1; i <= num; i++ {
	//	f, err := os.OpenFile("./"+strconv.Itoa(i)+".db", os.O_RDONLY, os.ModePerm)
	//	if err != nil {
	//		fmt.Println(err)
	//		return
	//	}
	//	b, err := ioutil.ReadAll(f)
	//	if err != nil {
	//		fmt.Println(err)
	//		return
	//	}
	//	fii.Write(b)
	//	f.Close()
	//}
}
